﻿using Castle.Facilities.NHibernateIntegration;
using Castle.Core.Configuration;
using Castle.MicroKernel.Registration;
using System.Linq;
using System;

namespace Inovout.Repositories
{
    internal class NHibernateExtensionFacility : NHibernateFacility
    {
        internal static IConfiguration GetNHibernateFacilityConfiguration(IApplication application)
        {
            IConfiguration dataSourceConfiguration = application.ApplicationConfiguration.Children.Single(c => c.Name.Equals("dataSource"));
            IConfiguration repositoriesConfiguration = dataSourceConfiguration.Children.SingleOrDefault(c=> c.Name.Equals("repositories"));
            IConfiguration databasesConfiguration = dataSourceConfiguration.Children.SingleOrDefault(c => c.Name.Equals("databases"));
            if (databasesConfiguration.Children.Count == 0)
            {
                throw new Exception("至少配置一个数据库");
            }
            if (repositoriesConfiguration == null)
            {
                IConfiguration firstDatabaseConfiguration = databasesConfiguration.Children[0];

                //IConfiguration repositoryConfiguration = new MutableConfiguration("repository");
                //repositoryConfiguration.Attributes.Add("name", firstDatabaseConfiguration.Attributes["name"]);
                //repositoryConfiguration.Attributes.Add("databaseName", firstDatabaseConfiguration.Attributes["name"]);


                repositoriesConfiguration = new MutableConfiguration("repositories");
                repositoriesConfiguration.Attributes.Add("defaultDatabase", firstDatabaseConfiguration.Attributes["name"]);
                //  repositoriesConfiguration.Children.Add(repositoryConfiguration);
                dataSourceConfiguration.Children.Add(repositoriesConfiguration);
            }

            foreach (IConfiguration databaseConfiguraton in databasesConfiguration.Children)
            {
                if (!databaseConfiguraton.Attributes.AllKeys.Contains("id"))
                {
                    databaseConfiguraton.Attributes.Add("id",databaseConfiguraton.Attributes["name"]);
                }
            }

            IConfiguration nhFacilityConfiguration = new MutableConfiguration("facility");
            nhFacilityConfiguration.Attributes["type"] = typeof(NHibernateExtensionFacility).AssemblyQualifiedName;
            nhFacilityConfiguration.Attributes["id"] = "nhibernatefacility";
            nhFacilityConfiguration.Attributes["configurationBuilder"] = typeof(DatabaseConfigurationBuilder).AssemblyQualifiedName;
            nhFacilityConfiguration.Children.AddRange(dataSourceConfiguration.Children["databases"].Children);
            return nhFacilityConfiguration;
        }

        private RepositoryConfigurationKeyDictionary repositoryConfigurationKeyDictionary;
        public NHibernateExtensionFacility()
            : base(new DatabaseConfigurationBuilder())
        {
            IConfiguration repositoryConfiguration = null;
            this.repositoryConfigurationKeyDictionary = new RepositoryConfigurationKeyDictionary(repositoryConfiguration);
        }
        protected override void Init()
        {
            base.Init();

            RegisterTypeSessionManager();

            repositoryConfigurationKeyDictionary.Init(FacilityConfig);
        }

        private const string TypeSessionManagerKey = "nhfacility.typesessionmanager";
        protected virtual void RegisterTypeSessionManager()
        {

            Kernel.Register(Component.For<RepositoryConfigurationKeyDictionary>().Instance(repositoryConfigurationKeyDictionary));

            Kernel.Register(Component.For<ITypeSessionManager>()
                .ImplementedBy<TypeSessionManager>()
                .Named(TypeSessionManagerKey));
            Kernel.Register(Component.For<ISessionManager>()
                .ImplementedBy<TypeSessionManager>());

        }

    }
}
